package wiki_playground_dimitar;

import codeanticode.glgraphics.GLTexture;
import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PVector;
import toxi.geom.Vec3D;

public class FisheyeTest_005 extends PApplet{

	/**
	 * @param args
	 */
	
	float xPos =-300;
	float yPos =-300;
	float zPos =30;
	boolean orthoOn = true;
	private static float SPHERICAL_ANGLE = PI;
	public Ticle[] ticles;
	boolean edgesOn = false;
	boolean showGrid = true;
	QuadF qf;
	PImage img;
	GLTexture glt;
	//String ImagePath = "E:\\projects\\eclipse_projects\\miscCoding\\src\\data\\";
	
	public void setup() {
		size(800,800,OPENGL);
		ticles = new Ticle[200];
		for (int i = 0; i < ticles.length; i++) {
			ticles[i] = new Ticle(ticles);
		}
		ticles[0].setSize(50f);
		ticles[0].setPos(new PVector(random(-50,50),random(-50,50),random(height/2,height)));
		qf = new QuadF(new PVector(0,0,100f), null, 200f, 200f, 20, "XY");
		img = loadImage(dataPath("")+"icosa_003_left_00024.jpg");
		glt = new GLTexture(this, dataPath("")+"icosa_003_left_00024.jpg");
		qf.setTexture(glt);
	}
	
	public void draw() {
		background(127);
		if(orthoOn) {
			ortho(0, width, 0, height, -height*2f, height*2f);
			translate(width,0,0);
			//rotateY(HALF_PI*0.5f);
			//rotateX(map(mouseY,0,height,-PI,PI));

		} else {
			translate(width/2,height/2f,0);
			//rotateY(HALF_PI*0.5f);
			//rotateX(map(mouseY,0,height,-PI,PI));
		}
	drawSampleCube();
	qf.rotY(ticles[0].pos, -TWO_PI/720f);
	qf.rotZ(qf.pos, TWO_PI/720f);
	//qf.move(0,1,0);
	qf.display();
		for (int i = 0; i < ticles.length; i++) {
			//ticles[i].move(1,0, -1);
			//ticles[i].move(0,1, 0);
			//ticles[i].move(1,0, 0);
			//ticles[i].rotX(new PVector(0,0,height), TWO_PI/1440f);
			ticles[i].rotY(ticles[0].pos, TWO_PI/720f);
			ticles[i].display();
		}
		
	}
	
	private void drawCube(PVector pos, float size, int res, int[] c) {
		noStroke();
		fill(color(c[0]));
		drawQuad(pos.x,pos.y,pos.z+size*0.5f,size, res, true, "XY");
		drawQuad(pos.x,pos.y,pos.z-size*0.5f,size, res, true, "XY");
		fill(color(c[1]));
		drawQuad(pos.x+size*0.5f,pos.y,pos.z,size, res, true, "YZ");
		drawQuad(pos.x-size*0.5f,pos.y,pos.z,size, res, true, "YZ");
		fill(color(c[2]));
		drawQuad(pos.x,pos.y+size*0.5f,pos.z,size, res, true, "XZ");
		drawQuad(pos.x,pos.y-size*0.5f,pos.z,size, res, true, "XZ");
	}
	
	private void drawSampleCube() {
		stroke(255);
		fill(255,0,0,127);
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800),zPos+50f,100f, 10, true, "XY");
		drawQuad(map(mouseX,0,width,-800,800)+50f,map(mouseY,0,height,-800,800),zPos,100f, 10, true, "YZ");
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800)+50f,zPos,100f, 10, true, "XZ");
		noFill();
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800),zPos-50f,100f, 10, true, "XY");
		drawQuad(map(mouseX,0,width,-800,800)-50f,map(mouseY,0,height,-800,800),zPos,100f, 10, true, "YZ");
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800)-50f,zPos,100f, 10, true, "XZ");
		fill(0,255,0,127);
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800),zPos+50f,100f, 10, false, "XY");
		drawQuad(map(mouseX,0,width,-800,800)+50f,map(mouseY,0,height,-800,800),zPos,100f, 10, false, "YZ");
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800)+50f,zPos,100f, 10, false, "XZ");
		noFill();
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800),zPos-50f,100f, 10, false, "XY");
		drawQuad(map(mouseX,0,width,-800,800)-50f,map(mouseY,0,height,-800,800),zPos,100f, 10, false, "YZ");
		drawQuad(map(mouseX,0,width,-800,800),map(mouseY,0,height,-800,800)-50f,zPos,100f, 10, false, "XZ");
	}
	
	
private void drawQuad(float xPos, float yPos, float zPos, float size, int res, boolean fisheyeIsOn, String MODE) {
		
		PVector[] v = new PVector[4];
		v[0] = new PVector();
		v[1] = new PVector();
		v[2] = new PVector();
		v[3] = new PVector();
		if (MODE.equalsIgnoreCase("XY")) {
			v[0] = new PVector (xPos-size*0.5f,yPos-size*0.5f,zPos);
			v[1] = new PVector (xPos+size*0.5f,yPos-size*0.5f,zPos);
			v[2] = new PVector (xPos+size*0.5f,yPos+size*0.5f,zPos);
			v[3] = new PVector (xPos-size*0.5f,yPos+size*0.5f,zPos);
		}
		
		if (MODE.equalsIgnoreCase("YZ")) {
			v[0] = new PVector (xPos,yPos-size*0.5f,zPos-size*0.5f);
			v[1] = new PVector (xPos,yPos-size*0.5f,zPos+size*0.5f);
			v[2] = new PVector (xPos,yPos+size*0.5f,zPos+size*0.5f);
			v[3] = new PVector (xPos,yPos+size*0.5f,zPos-size*0.5f);
		}
		
		if (MODE.equalsIgnoreCase("XZ")) {
			v[0] = new PVector (xPos-size*0.5f,yPos,zPos-size*0.5f);
			v[1] = new PVector (xPos-size*0.5f,yPos,zPos+size*0.5f);
			v[2] = new PVector (xPos+size*0.5f,yPos,zPos+size*0.5f);
			v[3] = new PVector (xPos+size*0.5f,yPos,zPos-size*0.5f);
		}
		
		
		float myInc = 1f/(float)res;
		if (fisheyeIsOn) {
			for (int i = 0; i < res; i++) {
				for (int j = 0; j < res; j++) {
					beginShape();
						vertexF(
								((v[3].x-v[0].x)*j*myInc+v[0].x-((v[2].x-v[1].x)*j*myInc+v[1].x))*i*myInc+(v[2].x-v[1].x)*j*myInc+v[1].x,								
								((v[3].y-v[0].y)*j*myInc+v[0].y-((v[2].y-v[1].y)*j*myInc+v[1].y))*i*myInc+(v[2].y-v[1].y)*j*myInc+v[1].y,
								((v[3].z-v[0].z)*j*myInc+v[0].z-((v[2].z-v[1].z)*j*myInc+v[1].z))*i*myInc+(v[2].z-v[1].z)*j*myInc+v[1].z,
								height*0.5f);
						vertexF(
								((v[3].x-v[0].x)*(j+1)*myInc+v[0].x-((v[2].x-v[1].x)*(j+1)*myInc+v[1].x))*i*myInc+(v[2].x-v[1].x)*(j+1)*myInc+v[1].x,
								((v[3].y-v[0].y)*(j+1)*myInc+v[0].y-((v[2].y-v[1].y)*(j+1)*myInc+v[1].y))*i*myInc+(v[2].y-v[1].y)*(j+1)*myInc+v[1].y,
								((v[3].z-v[0].z)*(j+1)*myInc+v[0].z-((v[2].z-v[1].z)*(j+1)*myInc+v[1].z))*i*myInc+(v[2].z-v[1].z)*(j+1)*myInc+v[1].z,
								height*0.5f);
						vertexF(
								((v[3].x-v[0].x)*(j+1)*myInc+v[0].x-((v[2].x-v[1].x)*(j+1)*myInc+v[1].x))*(i+1)*myInc+(v[2].x-v[1].x)*(j+1)*myInc+v[1].x,
								((v[3].y-v[0].y)*(j+1)*myInc+v[0].y-((v[2].y-v[1].y)*(j+1)*myInc+v[1].y))*(i+1)*myInc+(v[2].y-v[1].y)*(j+1)*myInc+v[1].y,
								((v[3].z-v[0].z)*(j+1)*myInc+v[0].z-((v[2].z-v[1].z)*(j+1)*myInc+v[1].z))*(i+1)*myInc+(v[2].z-v[1].z)*(j+1)*myInc+v[1].z,
								height*0.5f);
						vertexF(
								((v[3].x-v[0].x)*j*myInc+v[0].x-((v[2].x-v[1].x)*j*myInc+v[1].x))*(i+1)*myInc+(v[2].x-v[1].x)*j*myInc+v[1].x,
								((v[3].y-v[0].y)*j*myInc+v[0].y-((v[2].y-v[1].y)*j*myInc+v[1].y))*(i+1)*myInc+(v[2].y-v[1].y)*j*myInc+v[1].y,
								((v[3].z-v[0].z)*j*myInc+v[0].z-((v[2].z-v[1].z)*j*myInc+v[1].z))*(i+1)*myInc+(v[2].z-v[1].z)*j*myInc+v[1].z,
								height*0.5f);
						
						endShape(CLOSE);
				}
			}
		} else {
			for (int i = 0; i < res; i++) {
				for (int j = 0; j < res; j++) {
					beginShape();
					vertex(
							((v[3].x-v[0].x)*j*myInc+v[0].x-((v[2].x-v[1].x)*j*myInc+v[1].x))*i*myInc+(v[2].x-v[1].x)*j*myInc+v[1].x,								
							((v[3].y-v[0].y)*j*myInc+v[0].y-((v[2].y-v[1].y)*j*myInc+v[1].y))*i*myInc+(v[2].y-v[1].y)*j*myInc+v[1].y,
							((v[3].z-v[0].z)*j*myInc+v[0].z-((v[2].z-v[1].z)*j*myInc+v[1].z))*i*myInc+(v[2].z-v[1].z)*j*myInc+v[1].z);
					vertex(
							((v[3].x-v[0].x)*(j+1)*myInc+v[0].x-((v[2].x-v[1].x)*(j+1)*myInc+v[1].x))*i*myInc+(v[2].x-v[1].x)*(j+1)*myInc+v[1].x,
							((v[3].y-v[0].y)*(j+1)*myInc+v[0].y-((v[2].y-v[1].y)*(j+1)*myInc+v[1].y))*i*myInc+(v[2].y-v[1].y)*(j+1)*myInc+v[1].y,
							((v[3].z-v[0].z)*(j+1)*myInc+v[0].z-((v[2].z-v[1].z)*(j+1)*myInc+v[1].z))*i*myInc+(v[2].z-v[1].z)*(j+1)*myInc+v[1].z);
					vertex(
							((v[3].x-v[0].x)*(j+1)*myInc+v[0].x-((v[2].x-v[1].x)*(j+1)*myInc+v[1].x))*(i+1)*myInc+(v[2].x-v[1].x)*(j+1)*myInc+v[1].x,
							((v[3].y-v[0].y)*(j+1)*myInc+v[0].y-((v[2].y-v[1].y)*(j+1)*myInc+v[1].y))*(i+1)*myInc+(v[2].y-v[1].y)*(j+1)*myInc+v[1].y,
							((v[3].z-v[0].z)*(j+1)*myInc+v[0].z-((v[2].z-v[1].z)*(j+1)*myInc+v[1].z))*(i+1)*myInc+(v[2].z-v[1].z)*(j+1)*myInc+v[1].z);
					vertex(
							((v[3].x-v[0].x)*j*myInc+v[0].x-((v[2].x-v[1].x)*j*myInc+v[1].x))*(i+1)*myInc+(v[2].x-v[1].x)*j*myInc+v[1].x,
							((v[3].y-v[0].y)*j*myInc+v[0].y-((v[2].y-v[1].y)*j*myInc+v[1].y))*(i+1)*myInc+(v[2].y-v[1].y)*j*myInc+v[1].y,
							((v[3].z-v[0].z)*j*myInc+v[0].z-((v[2].z-v[1].z)*j*myInc+v[1].z))*(i+1)*myInc+(v[2].z-v[1].z)*j*myInc+v[1].z);
					endShape();
			} 
			}
		}
	}

	
	private void vertexF(float x, float y, float z, float r) {	
		float theta = acos(z/sqrt(x*x+y*y+z*z));
		float radius = theta/SPHERICAL_ANGLE*r*2;
		float phi = atan2(y,x);
		float xP = cos(phi)*radius;
		float yP = sin(phi)*radius;
		float zP;
		zP = -Math.signum(z)*sqrt(x*x+y*y+z*z);
		vertex(xP,yP,zP);
	}	

	private void vertexF(float x, float y, float z) {	
		float theta = acos(z/sqrt(x*x+y*y+z*z));
		float radius = theta/SPHERICAL_ANGLE*height;
		float phi = atan2(y,x);
		float xP = cos(phi)*radius;
		float yP = sin(phi)*radius;
		float zP;
		zP = Math.signum(z)*sqrt(x*x+y*y+z*z);
		vertex(xP,yP,zP);
	}	
	private void vertexF(PVector v) {
		float x = v.x;
		float y = v.y;
		float z = v.z;
		float theta = acos(z/sqrt(x*x+y*y+z*z));
		float radius = theta/SPHERICAL_ANGLE*height;
		float phi = atan2(y,x);
		float xP = cos(phi)*radius;
		float yP = sin(phi)*radius;
		float zP;
		zP = Math.signum(z)*sqrt(x*x+y*y+z*z);
		vertex(xP,yP,zP);
	}	
	private void vertexF(PVector v, float sCoord,float tCoord) {
		float x = v.x;
		float y = v.y;
		float z = v.z;
		float theta = acos(z/sqrt(x*x+y*y+z*z));
		float radius = theta/SPHERICAL_ANGLE*height;
		float phi = atan2(y,x);
		float xP = cos(phi)*radius;
		float yP = sin(phi)*radius;
		float zP;
		zP = Math.signum(z)*sqrt(x*x+y*y+z*z);
		vertex(xP,yP,zP,sCoord,tCoord);
	}	
	private void vertex(PVector v) {
		vertex(v.x,v.y,v.z);
	}
	private void vertex(PVector v,float sCoord, float tCoord) {
		vertex(v.x,v.y,v.z,sCoord,tCoord);
	}
	
	
	private PVector vectorF(PVector v) {
		float x = v.x;
		float y = v.y;
		float z = v.z;
		float theta = acos(z/sqrt(x*x+y*y+z*z));
		float radius = theta/SPHERICAL_ANGLE*height;
		float phi = atan2(y,x);
		float xP = cos(phi)*radius;
		float yP = sin(phi)*radius;
		float zP;
		zP = Math.signum(z)*sqrt(x*x+y*y+z*z);
		return new PVector(xP,yP,zP);
	}	

	public PVector rotateZ(PVector o, PVector v, float phi) {
				PVector result = new PVector();
				float x =v.x - o.x;
				float y =v.y - o.y;
				//float z =v.z - o.z;
				result.x = x*cos(phi)-y*sin(phi)+o.x;
				result.y = x*sin(phi)+y*cos(phi)+o.y;
				result.z = v.z;
		return result;
	}
	
	public PVector rotateX(PVector o, PVector v, float phi) {
		PVector result = new PVector();
		//float x =v.x - o.x;
		float y =v.y - o.y;
		float z =v.z - o.z;
		result.x = v.x;
		result.y = z*sin(phi)+y*cos(phi)+o.y;
		result.z = z*cos(phi)-y*sin(phi)+o.z;
		return result;
	}

	public PVector rotateY(PVector o, PVector v, float phi) {
		PVector result = new PVector();
		float x =v.x - o.x;
		//float y =v.y - o.y;
		float z =v.z - o.z;
		result.x = x*cos(phi)-z*sin(phi)+o.x;
		result.y = v.y;
		result.z = x*sin(phi)+z*cos(phi)+o.z;
		return result;
	}	
	
	
	//under construction!
	public class QuadF {
		public PVector pos;
		public PVector posF;
		public PVector[] corners;
		public PVector[][] vertices;
		public PVector[][] verticesF;
		public float width, height;
		public int RES;
		public PImage pTex;
		public GLTexture gTex;
		String[] MODES = {"XY","YZ","XZ","FREE"};
		String MODE; 
		boolean texOn = false;
		public boolean flipX, flipY, rot90,rot270;
		boolean showGrid = true;
		int myColor = color(127,0,255);
		
		
		public QuadF (PVector thePos, PVector[] theCorners, float theWidth, float theHeight, int theRes, String theMode) {
			pos = thePos;
			width = theWidth;
			height = theHeight;
			RES = theRes;
			vertices = new PVector[RES+1][RES+1];
			verticesF = new PVector[RES+1][RES+1];
			if (theCorners == null || theCorners.length != 4) {
				MODE = theMode;
				initCorners();
			} else {
				//in this case, width and height will actually be ignored
				corners = theCorners;
				MODE = "FREE";
			}
			setVertices();
		}
		
		public void display() {
			if (pTex == null && gTex == null) {
				if (showGrid) {
					stroke(255);
					strokeWeight(1);
				} else {
					noStroke();
				}
				fill(color(myColor));
				for (int j = 0; j < vertices.length-1;j++ ) {
					beginShape(QUAD_STRIP);
					for (int i = 0; i < vertices[0].length; i++) {
						vertex(verticesF[i][j]);
						vertex(verticesF[i][j+1]);
					}
					endShape();
				}
			} else {
				if (gTex == null) {
					
					float wInc = pTex.width/(float)RES;
					float hInc = pTex.height/(float)RES;
					for (int j = 0; j < vertices.length-1;j++ ) {
						beginShape(QUAD_STRIP);
						texture(pTex);
						for (int i = 0; i < vertices[0].length; i++) {
							vertex(verticesF[i][j],wInc*i,hInc*j);
							vertex(verticesF[i][j+1],wInc*i,hInc*(j+1));
						}
						endShape();
					}
				} else {
					float wInc = gTex.width/(float)RES;
					float hInc = gTex.height/(float)RES;
					for (int j = 0; j < vertices.length-1;j++ ) {
						beginShape(QUAD_STRIP);
						texture(gTex);
						for (int i = 0; i < vertices[0].length; i++) {
							vertex(verticesF[i][j],wInc*i,hInc*j);
							vertex(verticesF[i][j+1],wInc*i,hInc*(j+1));
						}
						endShape();
					}
				}

				}
		}
		
		public void setTexture(PImage theTex) {
			pTex = theTex;
		}
		
		public void setTexture(GLTexture theTex) {
			gTex = theTex;
		}
		
		public void setVertices () {
			float myInc = 1f/(float)RES;
				for (int i = 0; i <= RES; i++) {
					for (int j = 0; j <= RES; j++) {
							vertices[i][j] = new PVector (
									((corners[3].x-corners[0].x)*j*myInc+corners[0].x-((corners[2].x-corners[1].x)*j*myInc+corners[1].x))*i*myInc+(corners[2].x-corners[1].x)*j*myInc+corners[1].x,								
									((corners[3].y-corners[0].y)*j*myInc+corners[0].y-((corners[2].y-corners[1].y)*j*myInc+corners[1].y))*i*myInc+(corners[2].y-corners[1].y)*j*myInc+corners[1].y,
									((corners[3].z-corners[0].z)*j*myInc+corners[0].z-((corners[2].z-corners[1].z)*j*myInc+corners[1].z))*i*myInc+(corners[2].z-corners[1].z)*j*myInc+corners[1].z);
							verticesF[i][j] = vectorF(vertices[i][j]);
					}			
				}
		}
		
		public void initCorners() {
			corners = new PVector[4];
			corners[0] = new PVector();
			corners[1] = new PVector();
			corners[2] = new PVector();
			corners[3] = new PVector();
			if (MODE.equalsIgnoreCase("XY")) {
				corners[0] = new PVector (pos.x-width*0.5f,pos.y-height*0.5f,pos.z);
				corners[1] = new PVector (pos.x+width*0.5f,pos.y-height*0.5f,pos.z);
				corners[2] = new PVector (pos.x+width*0.5f,pos.y+height*0.5f,pos.z);
				corners[3] = new PVector (pos.x-width*0.5f,pos.y+height*0.5f,pos.z);
			}
			
			if (MODE.equalsIgnoreCase("YZ")) {
				corners[0] = new PVector (pos.x,pos.y-width*0.5f,pos.z-height*0.5f);
				corners[1] = new PVector (pos.x,pos.y-width*0.5f,pos.z+height*0.5f);
				corners[2] = new PVector (pos.x,pos.y+width*0.5f,pos.z+height*0.5f);
				corners[3] = new PVector (pos.x,pos.y+width*0.5f,pos.z-height*0.5f);
			}
			
			if (MODE.equalsIgnoreCase("XZ")) {
				corners[0] = new PVector (pos.x-width*0.5f,pos.y,pos.z-height*0.5f);
				corners[1] = new PVector (pos.x-width*0.5f,pos.y,pos.z+height*0.5f);
				corners[2] = new PVector (pos.x+width*0.5f,pos.y,pos.z+height*0.5f);
				corners[3] = new PVector (pos.x+width*0.5f,pos.y,pos.z-height*0.5f);
			}
			
		}
		
		public void move(float theX, float theY, float theZ) {
			pos.set(pos.x+theX, pos.y+theY, pos.z+theZ);
			posF = vectorF(pos);
			corners[0].set(corners[0].x+theX,corners[0].y+theY,corners[0].z+theZ);
			corners[1].set(corners[1].x+theX,corners[1].y+theY,corners[1].z+theZ);
			corners[2].set(corners[2].x+theX,corners[2].y+theY,corners[2].z+theZ);
			corners[3].set(corners[3].x+theX,corners[3].y+theY,corners[3].z+theZ);
			setVertices();
		}
		
		public void rotX(PVector o, float phi) {
			pos = rotateX(o,pos,phi);
			posF = vectorF(pos);
			corners[0] = rotateX(o,corners[0],phi);
			corners[1] = rotateX(o,corners[1],phi);
			corners[2] = rotateX(o,corners[2],phi);
			corners[3] = rotateX(o,corners[3],phi);
			setVertices();
		}
		public void rotY(PVector o, float phi) {
			pos = rotateY(o,pos,phi);
			posF = vectorF(pos);
			corners[0] = rotateY(o,corners[0],phi);
			corners[1] = rotateY(o,corners[1],phi);
			corners[2] = rotateY(o,corners[2],phi);
			corners[3] = rotateY(o,corners[3],phi);
			setVertices();
		}
		public void rotZ(PVector o, float phi) {
			pos = rotateZ(o,pos,phi);
			posF = vectorF(pos);
			corners[0] = rotateZ(o,corners[0],phi);
			corners[1] = rotateZ(o,corners[1],phi);
			corners[2] = rotateZ(o,corners[2],phi);
			corners[3] = rotateZ(o,corners[3],phi);
			setVertices();
		}

		
	}
	
	public class Ticle {
		public PVector pos;
		public PVector posF;
		float size = 10f;
		Ticle[] myTicles;
		int[] myTicleBuddies;
		private int MAX_BUDDIES = 3;
		float dist;
		int MAX_RES = 20;
		String[] MODES = {"CARTESIAN_AXE","BOX"};
		int MODE = 0; 
		
		public Ticle (Ticle[] theTicles) {
			myTicles = theTicles;
			init();
		}
		
		public void init() {
			pos = new PVector(random(-height*2f,height*2f),random(-height*2f,height*2f),random(-height*0.5f,height*1.5f));
			myTicleBuddies = new int[MAX_BUDDIES];
			for (int i = 0; i < myTicleBuddies.length; i++) {
				myTicleBuddies[i] = floor(random(myTicles.length));
			}
			dist = sqrt(sq(pos.x)+sq(pos.y)+sq(pos.z));
			if (dist > height) {
				pos.normalize();
				pos.mult(height-10f);
			}
			posF = vectorF(pos);
		}
		
		private void drawAxes() {
			stroke(255);
			noFill();
			beginShape();
			vertexF(pos.x-size, pos.y, pos.z);
			vertexF(pos.x, pos.y, pos.z);
			vertexF(pos.x+size, pos.y, pos.z);
			endShape();
			beginShape();
			vertexF(pos.x, pos.y-size, pos.z);
			vertexF(pos.x, pos.y, pos.z);
			vertexF(pos.x, pos.y+size, pos.z);
			endShape();
			beginShape();
			vertexF(pos.x, pos.y, pos.z-size);
			vertexF(pos.x, pos.y, pos.z);
			vertexF(pos.x, pos.y, pos.z+size);
			endShape();
			if (edgesOn ) drawEdges();
		}
		
		private void drawBox () {
			int[] myColors = {color(0,127,255),color(0,63,127),color(0,31,63)};
			drawCube(this.pos, this.size*10f, floor(this.MAX_RES*0.25f), myColors);
			//drawCube(this.pos, this.size*10f, 1, myColors);
			if (edgesOn ) drawEdges();
		}
		
		private void drawEdges() {
			stroke(255,255,0,63);
			noFill();
			for (int i = 0; i < myTicleBuddies.length; i++) {
				//int res = floor(1/(1f+sqrt(dist*myTicles[myTicleBuddies[i]].dist)))*MAX_RES;
				//int res = sqrt(pos.z+height*0.5f)*myTicles[myTicleBuddies[i]].pos.z*MAX_RES;
				//float d = PVector.dist(posF, myTicles[myTicleBuddies[i]].posF);
				//int res = (int)(height/d*MAX_RES);
				int res = MAX_RES;
				//System.out.println(res);
				beginShape();
				float x0 = pos.x;
				float y0 = pos.y;
				float z0 = pos.z;
				float x1 = myTicles[myTicleBuddies[i]].pos.x;
				float y1 = myTicles[myTicleBuddies[i]].pos.y;
				float z1 = myTicles[myTicleBuddies[i]].pos.z;
				vertexF(x0, y0, z0);
				float myInc = 1/(float)res;
				for (int j = 0; j < res; j++) {
					vertexF((x1-x0)*j*myInc+x0,(y1-y0)*j*myInc+y0,(z1-z0)*j*myInc+z0);
				}
				vertexF(x1, y1, z1);
				endShape();				
			}
		}
		
		public void display() {
				switch (MODE) {
				case (0) : drawAxes();
				break;
				case (1) : drawBox();
				break;
				}
			
					}
		
		public void move(float theX, float theY, float theZ) {
			pos.set(pos.x+theX, pos.y+theY, pos.z+theZ);
			dist = sqrt(sq(pos.x)+sq(pos.y)+sq(pos.z));
			posF = vectorF(pos);
			//if (pos.z < -height*0.5f || pos.z > height*1.5f || pos.x < -height*2f || pos.x > height*2f || pos.y < -height*2f || pos.y > height*2f) init();
			if (dist > height ) init();
		}
		
		public void rotX(PVector o, float phi) {
			pos = rotateX(o,pos,phi);
			posF = vectorF(pos);
		}
		
		public void rotY(PVector o, float phi) {
			pos = rotateY(o,pos,phi);
			posF = vectorF(pos);
		}
		
		public void rotZ(PVector o, float phi) {
			pos = rotateZ(o,pos,phi);
			posF = vectorF(pos);
		}
		
		public void setSize(float newSize) {
			size = newSize;
		}
		
		public void setPos(PVector newPos) {
			pos = newPos;
		}
		
	}
	
	
	public void keyPressed() {
		if (key == 'r') {
			zPos +=10f;
			System.out.println("zPos: " + zPos);
		}
		if (key == 'f') {
			zPos -=10f;
			System.out.println("zPos: " + zPos);
		}
		if (key == 't') {
			SPHERICAL_ANGLE = min(TWO_PI,SPHERICAL_ANGLE+TWO_PI/72f);
			System.out.println("spherical angle: " + degrees(SPHERICAL_ANGLE));
		}
		if (key == 'g') {SPHERICAL_ANGLE = max(TWO_PI/72f,SPHERICAL_ANGLE-TWO_PI/72f);
			System.out.println("spherical angle: " + degrees(SPHERICAL_ANGLE));
		}
		
		if (key == 'e') edgesOn = !edgesOn;
		if (key == 'w') orthoOn = !orthoOn;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
